﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

namespace StyleMVVM.DependencyInjection
{
	public sealed class ThreadStaticLifeCycleContainer : ILifeCycleContainer
	{
		private bool isWeak;
		private DisposalScope disposalScope = new DisposalScope();

		[ThreadStatic]
		private static object instance;

		public ThreadStaticLifeCycleContainer(bool isWeak)
		{
			this.isWeak = isWeak;
		}

		public object RetrieveObject(IExportStrategy strategy,
		                             ExportLifeCycleMethod exportMethod,
		                             IDependencyInjectionContainer container,
		                             IInjectionContext injectionContext,
		                             [ReadOnlyArray] object[] constructorParams)
		{
			object returnValue = null;

			if (isWeak)
			{
				WeakReference weakReference = instance as WeakReference;

				if (weakReference != null)
				{
					returnValue = weakReference.Target;
				}

				if (returnValue == null)
				{
					IDisposalScope oldScope = injectionContext.DisposalScope;

					injectionContext.DisposalScope = null;

					returnValue = exportMethod(injectionContext, constructorParams);

					injectionContext.DisposalScope = oldScope;

					if (returnValue != null)
					{
						instance = new WeakReference(returnValue);
					}
				}
			}
			else
			{
				returnValue = instance;

				if (returnValue == null)
				{
					IDisposalScope oldScope = injectionContext.DisposalScope;

					injectionContext.DisposalScope = disposalScope;

					returnValue = exportMethod(injectionContext, constructorParams);

					injectionContext.DisposalScope = oldScope;

					instance = returnValue;
				}
			}

			return returnValue;
		}

		public void Shutdown()
		{
			instance = null;

			disposalScope.Dispose();

			disposalScope = null;
		}
	}
}